﻿package cn.onecloud.service.cmdb.role;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.annotation.Resource;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.session.SessionInformation;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.stereotype.Service;

import cn.onecloud.dao.cmdb.role.MenuDao;
import cn.onecloud.dao.cmdb.role.Role_MenuDao;
import cn.onecloud.dao.cmdb.role.UserDao;
import cn.onecloud.dao.cmdb.role.User_RoleDao;
import cn.onecloud.model.cmdb.menu.Menu;
import cn.onecloud.model.cmdb.menu.Role_Menu;
import cn.onecloud.model.cmdb.menu.User;
import cn.onecloud.security.impl.SecurityMetadataSourceImpl;
import cn.onecloud.util.StaticMethod;

@Service("secuManager")
public class SecuManager {

	private MenuDao menuDao;
	@Resource(name="menuDao")
	public void setMenuDao(MenuDao menuDao) {
		this.menuDao = menuDao;
	}
	@Autowired
	private SessionRegistry sessionRegistry;
	/**
	 * 因为类交给spring管理，会映射成静态类型(Ioc容器中的单例)，所以它们加static后所指向的对象是相同的
	 */
	private static UserDao userDao;
	@Resource(name="userDao")
	public void setUserDao(UserDao userDao) {
		SecuManager.userDao = userDao;
	}
	private static User_RoleDao user_RoleDao;
	@Resource(name="userRoleDao")
	public void setUser_RoleDao(User_RoleDao user_RoleDao) {
		SecuManager.user_RoleDao = user_RoleDao;
	}
	private static Role_MenuDao role_MenuDao;
	@Resource(name="roleMenuDao")
	public void setRole_MenuDao(Role_MenuDao role_MenuDao) {
		SecuManager.role_MenuDao = role_MenuDao;
	}
//r
	/**
	 * 初始化权限与角色的关系，保存在Map<url, Collection<roleId>> resourceMapHash中
	 */
	public void initAll_RA_() {
		if (SecurityMetadataSourceImpl.menuMap == null)
			SecurityMetadataSourceImpl.menuMap = new HashMap<String, Collection<ConfigAttribute>>();
		if (SecurityMetadataSourceImpl.menuMap.isEmpty()) {
			Iterator<Menu> menus = this.menuDao.getAll_AR_().iterator();
			while (menus.hasNext()) {
				Menu menu = menus.next();
				Collection<ConfigAttribute> configAttributes = new HashSet<ConfigAttribute>();
				Iterator<Role_Menu> role_Menus = menu.getRoleMenus().iterator();
				// 类SecurityConfig实现了equals和hashCode方法
				// 使用HashSet时，将不会添加重复项
				while (role_Menus.hasNext()) {
					int rId = role_Menus.next().getRole().getId();
					configAttributes.add(new SecurityConfig(String.valueOf(rId)));
				}
				// 封装资源的内容(url,action)和资源对应的角色(role)
				SecurityMetadataSourceImpl.menuMap.put(menu.getUrl(), configAttributes);
			}
		}
		System.out.println("***读取角色-权限成功.SecuManager.initAll_RA_***");
	}
	/**
	 * 刷新权限与角色的关系
	 */
	public void refreshAll_RA_() {
		SecurityMetadataSourceImpl.menuMap.clear();
		initAll_RA_();
	}
	/**
	 * 初始化菜单
	 */
	public void initMenu() {
		if (SecurityMetadataSourceImpl.menuList == null)
			SecurityMetadataSourceImpl.menuList = new ArrayList<Menu>();
		SecurityMetadataSourceImpl.menuList = this.menuDao.getAsOnsd();
		if(SecurityMetadataSourceImpl.defaultMenu == null)
			SecurityMetadataSourceImpl.defaultMenu = new HashSet<Integer>();
		List<Integer> aids = this.menuDao.getA_OnNoRole();
		if(aids != null)
			for(int id : aids) {
				SecurityMetadataSourceImpl.defaultMenu.add(id);
			}
		System.out.println("***生成菜单成功.SecuManager.initMenu***");
	}
	/**
	 * 刷新数据
	 */
	public void refreshMenu() {
		SecurityMetadataSourceImpl.menuList.clear();
		SecurityMetadataSourceImpl.defaultMenu.clear();
		initMenu();
	}
	
//static method
	/**
	 * 根据账号查找用户的详细信息及角色
	 * @param account
	 * @return
	 */
	public static User findUserR_ByU_a(String account) {
		User user = userDao.getUserByU_a(account);
		user.setUser_roles(user_RoleDao.getU_R_ByUId(user.getId()));
		return user;
	}
	/**
	 * 根据角色id查找菜单(权限)id
	 * @param rids
	 * @return
	 */
	public static List<Integer> findMenuByRIds(String rids) {
		return role_MenuDao.getAIdsByRIds(rids);
	}
	/**
	 * 获取属于自己的菜单
	 * @return [{id:1,name:"",action:"",pId:2}]
	 */
	@SuppressWarnings("unchecked")
	public static String findMenu() {
		
		Set<Integer> userMenu;
		try {
			userMenu = ((org.springframework.security.core.userdetails.User)
					SecurityContextHolder.getContext()
						.getAuthentication().getPrincipal())
						.getUserMenu();
		} catch(Exception e) {
			userMenu = new HashSet<Integer>();
		}
		JSONArray array = new JSONArray();
		for(Menu a : SecurityMetadataSourceImpl.menuList) {
			if(SecurityMetadataSourceImpl.defaultMenu.contains(a.getId())
					|| userMenu.contains(a.getId())) {
				JSONObject menuJson = new JSONObject();
				menuJson.put("id", a.getId());
				menuJson.put("name", a.getName());
				menuJson.put("action", a.getUrl());
				//\"open\":true
				if(a.getParent() != null) {
					menuJson.put("pId", a.getParent().getId());
				}
				array.add(menuJson);
			}
		}
		return array.toString();
	}
	/**
	 * 当前用户id
	 * @return 未登录返回  0
	 */
	public static int currentId() {
		try {
			return ((org.springframework.security.core.userdetails.User) 
					SecurityContextHolder.getContext().getAuthentication().getPrincipal())
					.getId()[0];
		} catch(ClassCastException e) {
			return 0;
		}
	}
	/**
	 * 当前用户账号
	 * @return 未登录返回  ""
	 */
	public static String currentAccount() {
		try {
			return ((org.springframework.security.core.userdetails.User)
					SecurityContextHolder.getContext().getAuthentication().getPrincipal())
					.getUsername();
		} catch(ClassCastException e) {
			return "";
		}
	}
	/**
	 * 当前用户姓名
	 * @return 未登录返回  ""
	 */
	public static String currentName() {
		try {
			return ((org.springframework.security.core.userdetails.User) 
					SecurityContextHolder.getContext().getAuthentication().getPrincipal())
					.getStr()[0];
		} catch(ClassCastException e) {
			return "";
		}
	}
	/**
	 * 当前用户
	 * @return 未登录返回  null
	 */
	public static org.springframework.security.core.userdetails.User currentUser() {
		try {
			return (org.springframework.security.core.userdetails.User)
					SecurityContextHolder.getContext().getAuthentication().getPrincipal();
		} catch(ClassCastException e) {
			return null;
		}
	}
	/**
	 * 当前用户ip
	 * @return 未登录返回  ""
	 */
	public static String currentIp() {
		try {
			return ((WebAuthenticationDetails) SecurityContextHolder.getContext()
					.getAuthentication().getDetails()).getRemoteAddress();
		} catch(Exception e) {
			return "";
		}
	}
	/**
	 * 当前用户id[]组
	 * @param i 0->id. 1->部门 . 2->值班父部门(不存在返回-1，顶层返回-2)
	 * @return 未登录返回 0
	 */
	public static int currentID(int i) {
		try {
			return ((org.springframework.security.core.userdetails.User) 
					SecurityContextHolder.getContext().getAuthentication().getPrincipal())
					.getId()[i];
		} catch(ClassCastException e) {
			return 0;
		}
	}
	/**
	 * 当前用户id[]组
	 * @return i 0->id. 1->部门 . 2->值班父部门(不存在返回-1，顶层返回-2) 未登录返回null
	 */
	public static int[] currentIds() {
		try {
			return ((org.springframework.security.core.userdetails.User) 
					SecurityContextHolder.getContext().getAuthentication().getPrincipal())
					.getId();
		} catch(ClassCastException e) {
			return null;
		}
	}
	/**(此种静态方法无效，放在userManager.java上有效)
	@Autowired
	private static SessionRegistry sessionRegistry;
 	//登录用户数
	public static int loginUserNums() {
		return sessionRegistry.getAllPrincipals().size();
	}
	*/
	/**
	 * 是否有权限访问
	 * @param url 访问的地址
	 * @return 0->未登录 	负数id号->有权限	正数id号->无权限
	 */
	public static int canAccess(String url) {
		try {
			org.springframework.security.core.userdetails.User u = 
					(org.springframework.security.core.userdetails.User) 
						SecurityContextHolder.getContext().getAuthentication().getPrincipal();
			Collection<? extends GrantedAuthority> auths = u.getAuthorities();
			if(!auths.isEmpty()) {
				Collection<ConfigAttribute> clt = SecurityMetadataSourceImpl.menuMap.get(url);
				if(clt == null) {
//System.out.println("[ " + url + " ] -> 未配置**");
					return u.getId()[0] * -1;
				}
				Iterator<ConfigAttribute> ite = clt.iterator();
				while(ite.hasNext()){
					String attr = ite.next().getAttribute();
					Iterator<? extends GrantedAuthority> itee = auths.iterator();
					while(itee.hasNext()) {
						if(itee.next().getAuthority().equals(attr)) {
//System.out.println("[ " + url + " ] -> 有权限访问**");
							return u.getId()[0] * -1;
						}
					}
				}
			}
//System.out.println("[ " + url + " ] -> 无权限访问**");
			return u.getId()[0];
		} catch(ClassCastException e) {
			return 0;
		}
	}
	
	public String findlgUser() {
		
		List<Object> slist = sessionRegistry.getAllPrincipals();
		StringBuilder json = new StringBuilder();
		json.append("共 " + sessionRegistry.getUserNum() + " 用户登录， " +
				sessionRegistry.getSessionNum() + " 处登录，服务器时间：" +
				StaticMethod.DateToString(new Date()) + "<br>");
		for(int i=0; i<slist.size(); i++) {
			org.springframework.security.core.userdetails.User u = 
					(org.springframework.security.core.userdetails.User) slist.get(i);
			json.append("第 " + (i+1) + " 个用户，账号： " + u.getUsername() + "<br>");
			//包括被限制登录用户
			List<SessionInformation> ilist = sessionRegistry.getAllSessions(u, true);
			json.append("----" + ilist.size() + " 处登录<br>");
			for(int j=0; j<ilist.size(); j++) {
				SessionInformation sif = ilist.get(j);
				u = (org.springframework.security.core.userdetails.User) sif.getPrincipal();
				json.append("--------" + (j+1) +
						" 用户名：" + u.getStr()[0] +
						" 最后访问时间：" + StaticMethod.DateToString(sif.getLastRequest()) +
						" ip：" +  sif.getRemoteIp() +
						//" session:" + sif.getSessionId() +
						//" 限制登录：" + sif.isExpired() +
						"<br>");
				//强制退出1.将其限制，2.将其移除，使用第一种比较好
				//sif.expireNow();
				//sessionRegistry.removeSessionInformation(sif.getSessionId());
			}
			json.append("<br>");
		}
		return json.toString();
	}
}
